package com.mxm.mirai.web;

import com.mxm.mirai.dao.Pay;
import com.mxm.mirai.dao.PayConfig;
import com.mxm.mirai.dao.User;
import com.mxm.mirai.jwt.JWTUtil;
import com.mxm.mirai.service.PayConfigService;
import com.mxm.mirai.service.PayService;
import com.mxm.mirai.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.IOUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Api(value = "支付")
@Controller
public class PayWeb {

    @Autowired
    PayService payService;
    @Autowired
    UserService userService;
    @Autowired
    PayConfigService payConfigService;


    @Value("classpath:templates/mould/paya.html")
    private Resource paya;
    @Value("classpath:templates/mould/payb.html")
    private Resource payb;

    private Pay pay=null;
    private User user = null;
    private PayConfig payConfig = null;
    SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd");

    StringBuffer buffer = null;
//    String token = "KDxlHLTeBUdGMmcmLCWf3Pxxxxxxxx"; //记得更改 http://codepay.fateqq.com 后台可设置
//    String codepay_id ="213xxx" ;//记得更改 http://codepay.fateqq.com 后台可获得
//    String notify_url="http://ip/codepay";//通知地址
//    String return_url="http://ip/pay_verification";//支付后同步跳转地址
//    String key = "uusnLquly8t6bSbDO8fxxxxxxxxxx";
    @ResponseBody
    @GetMapping("/getPayConfig")
    @RequiresRoles(logical = Logical.OR, value = {"admin"})
    @ApiOperation(value = "码支付配置信息获取", notes = "拥有 admin 权限可以访问该页面")
    public PayConfig getPayConfig(){
        return payConfigService.getPayConfig();
    }
    @ResponseBody
    @PostMapping("/UpdatePayConfig")
    @RequiresRoles(logical = Logical.OR, value = {"admin"})
    @ApiOperation(value = "码支付配置信息更新", notes = "拥有 admin 权限可以访问该页面")
    public Integer UpdatePayConfig(String token,String codepayid,String pkey){
        payConfig = new PayConfig();
        payConfig.setId(1);
        payConfig.setToken(token);
        payConfig.setCodepayid(codepayid);
        payConfig.setPkey(pkey);
        if(payConfigService.UpdatePayConfig(payConfig)>=0){
            return 0;
        }
        return 1;
    }
    @ResponseBody
    @GetMapping("/pay/{type}/{base64}")
    @ApiOperation(value = "支付页面", notes = "不拦截")
    public String pay(@PathVariable(name="base64") String base64,@PathVariable(name="type") Integer type){
        String name = "用户异常";
        try {
            name = JWTUtil.getUsername(new String(Base64.getDecoder().decode(base64), "UTF-8"));
        }catch (Exception e){}
        String html="支付系统错误！";
        try {
            if(type!=null && type==1){
                html = IOUtils.toString(paya.getInputStream(), Charset.forName("UTF-8")).replace("[用户]",name);
            }else {
                html = IOUtils.toString(payb.getInputStream(), Charset.forName("UTF-8")).replace("[用户]",name);
            }
        } catch (IOException e) {
        }
        return html;
    }
    /**
     *
     * @param price 金额
     * @param type 支付方式 1=支付宝 2=QQ钱包 3=微信支付。默认值：1
     * @param pay_id 用户ID
     * @param param 自定义参数(可留空) quota=可挂数  duedate=时间
     * @return
     */
    @GetMapping("/pay_zf")
    @ApiOperation(value = "支付付款页面", notes = "自动跳转，不拦截")
    public String getA(String price,String type,String pay_id,String param, HttpServletRequest request){
        if(price==null){
            price="1";
        }
        if(type==null){
            type="1";
        }
        payConfig = payConfigService.getPayConfig();
        String token = payConfig.getToken(); //记得更改 http://codepay.fateqq.com 后台可设置
        String codepay_id =payConfig.getCodepayid() ;//记得更改 http://codepay.fateqq.com 后台可获得
        StringBuffer urll = request.getRequestURL();
        String return_url = urll.delete(urll.length() - request.getRequestURI().length(), urll.length()).append("/").toString();
        //参数有中文则需要URL编码
        String url="https://api.xiuxiu888.com/creat_order?id="+codepay_id+"&pay_id="+pay_id+"&price="+price+"&type="+type+"&token="+token+"&param="+param+"&return_url="+return_url+"pay_verification";
        return "redirect:"+url;
    }
    @ResponseBody
    @GetMapping("/pay_verification")
    @ApiOperation(value = "支付成功订单验证页面", notes = "不拦截")
    public String pay_verification(String pay_no){
        //id=108027637306&userID=213765&pay_no=2020092622001412061457582179&pay_id=sssssssssss&price=0.10&param=null&status=0&trade_no=1160113163312137658370122341&endTime=1601131993&trueID=213765&mode=0&notify_count=0&qr_user=0&ok=1&type=1&money=0.10&pay_time=1601131647&tag=0&target=get&codepay_server_time=1601131657&sign=34cdf7875fdd89efabef3ae368044b38
        pay = payService.QueryPay(pay_no);
        System.out.println("pay:"+pay);
        System.out.println("pay_no:"+pay_no+"------"+pay.getPayno());
        if(pay==null || "".equals(pay)){
            return "<script>alert(\"订单不存在！\");window.location = '/admin';</script>";
        }
        if("".equals(pay.getPayno()) || null==pay.getPayno()){
            return "<script>alert(\"订单不存在！\");window.location = '/admin';</script>";
        }
        if(pay.getStatus()!=0){
            return "<script>alert(\"订单已失效！\");window.location = '/admin';</script>";
        }
        System.out.println("Param:"+pay.getParam());
        switch(pay.getParam()){
            case "quota" :
                user = userService.getUserByUsername(pay.getPayid());
                Double dda = Double.valueOf(pay.getMoney())/15;//15元一个
                Integer iii =dda.intValue();
                user.setQuota(user.getQuota()+iii);
                userService.UpdateUser(user);
                payService.UpdatePayByStatus(pay_no,200);
                return "<script>alert(\"购买成功！\");window.location = '/admin';</script>";
            case "duedate" :
                user = userService.getUserByUsername(pay.getPayid());
//                System.out.println("user1:"+user);
                Double ddb = Double.valueOf(pay.getMoney())/5;//5元续费1月
                Integer ddd =ddb.intValue();
                Calendar cal = Calendar.getInstance();
                cal.setTime(user.getDuedate());//设置起时间
                cal.add(Calendar.MONTH, ddd);//增加N个月
//                System.out.println("续费后的日期："+df.format(cal.getTime()));
                user.setDuedate(cal.getTime());
//                System.out.println("user2:"+user);
                userService.UpdateUser(user);
                payService.UpdatePayByStatus(pay_no,200);
                return "<script>alert(\"购买成功！\");window.location = '/admin';</script>";
            default :
                return "<script>alert(\"异常订单！\");window.location = '/admin';</script>";
        }
    }
    @ResponseBody
    @PostMapping("/codepay")
    @ApiOperation(value = "码支付通知接口", notes = "不拦截")
    public String getB(HttpServletRequest request){
        System.out.println("================触发支付================");
        Map<String,String> params = new HashMap<String,String>(); //申明hashMap变量储存接收到的参数名用于排序
        Map requestParams = request.getParameterMap(); //获取请求的全部参数
        System.out.println(requestParams.toString());
        String valueStr = ""; //申明字符变量 保存接收到的变量
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            valueStr = values[0];
            //乱码解决，这段代码在出现乱码时使用。如果sign不相等也可以使用这段代码转化
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
            params.put(name, valueStr);//增加到params保存
        }
        List<String> keys = new ArrayList<String>(params.keySet()); //转为数组
        Collections.sort(keys); //重新排序
        String prestr = "";
        String sign= params.get("sign"); //获取接收到的sign 参数
        for (int i = 0; i < keys.size(); i++) {//遍历拼接url 拼接成a=1&b=2 进行MD5签名
            String key_name = keys.get(i);
            String value = params.get(key_name);
            if(value== null || value.equals("") ||key_name.equals("sign")){ //跳过这些 不签名
                continue;
            }
            if (prestr.equals("")){
                prestr =  key_name + "=" + value;
            }else{
                prestr =  prestr +"&" + key_name + "=" + value;
            }
        }
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        String key = payConfigService.getPayConfig().getPkey();
        md.update((prestr+key).getBytes());
        String  mySign = new BigInteger(1, md.digest()).toString(16).toLowerCase();
        if(mySign.length()!=32)mySign="0"+mySign;
        System.out.println(mySign+"____"+sign);
        if(mySign.equals(sign)){
        //编码要匹配 编码不一致中文会导致加密结果不一致
        //参数合法处理业务
        pay = new Pay();
        String pay_no = request.getParameter("pay_no");//流水号
        String pay_id = request.getParameter("pay_id");//用户唯一标识
        String money = request.getParameter("money");//付款金额
        String price = request.getParameter("price");//提交的金额
        String userID = request.getParameter("userID");//提交的金额
        String param = request.getParameter("param");//自定义参数
        String status = request.getParameter("status");//状态
        pay.setPayno(pay_no);
        pay.setPayid(pay_id);
        pay.setMoney(money);
        pay.setPrice(price);
        pay.setUserid(Integer.parseInt(userID));
        pay.setParam(param);
        pay.setStatus(Integer.parseInt(status));
        payService.AddPay(pay);
        System.out.println(pay_no+" "+pay_id+" "+money+" "+price);
            return "ok";
        }else{
            //参数不合法
            return"fail";
        }
    }
}
